#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QtSql>
#include <QScreen>
#include <QStandardItemModel>
#include <QListWidgetItem>
#include <QCheckBox>
#include "xlsxdocument.h"// 添加QXlsx头文件
#include <QFileDialog>
#include <QMessageBox>
#include <vector>
#include <QRegularExpression>
#include <QSqlQuery>
#include <QElapsedTimer>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    ,widget(new ScreenShotWidget(this))
{
    ui->setupUi(this);


    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setHostName("127.0.0.1");
    db.setPort(3306);
    db.setDatabaseName( "text" ); // 设置你的数据库名称
    db.setUserName("root"); // 设置你的数据库用户名
    db.setPassword("521.wang.00"); // 设置你的数据库密码
    bool ok = db.open();
    if (ok){
        QMessageBox::information(this, "infor", "success");
    }
    else {
        QMessageBox::information(this, "infor", "open failed");
        qDebug()<<"error open database because"<<db.lastError().text();
    }

    /*
    QXlsx::Document xlsx;           // 创建一个excel
    xlsx.write("A1", "Hello Qt!");  // 在第一行第一列写入数据
    xlsx.saveAs("Test.xlsx");
*/
}



Widget::~Widget()
{
    delete ui;
}

bool Widget::isTableExists(QString &table)
{
    QSqlQuery query;
    QString dbName = "dome";
    QString work_sheet_name =  table;
    // QString sql = QString("show tables;");  // 查询数据库中是否存在表名
    QString sql = QString("SELECT 1 FROM information_schema.tables WHERE table_schema = '%1' AND table_name = '%2'").arg(dbName, work_sheet_name);
    if (!query.exec(sql)) {
        // 处理 SQL 执行错误
        QSqlError error = query.lastError();
        qDebug() << "SQL 执行错误:" << error.text();
        return false;
    }
    // 如果查询返回至少一行结果，则表存在
    return query.next();

}

void Widget::creatNewTable(QAxObject *work_sheet)
{
    // 获取表头
    QString work_sheet_name = work_sheet->property("Name").toString();  // 获取工作表名称
    QAxObject *used_range = work_sheet->querySubObject("UsedRange");  // 选取当前页面所有已使用单元格
    QAxObject *columns = used_range->querySubObject("Columns");
    int column_start = used_range->property("Column").toInt();  // 获取起始列
    int column_count = columns->property("Count").toInt();  // 获取列数

    // 使用 std::vector 存储表头信息
    std::vector<QString> keyType(column_count);
    static const QRegularExpression removeParenthesesRegex("[\\(\\)]");
    // 从第三行开始读取表头
    for (int i = column_start; i < column_count + column_start; i++)  // 获取表头
    {
        QAxObject *cell = work_sheet->querySubObject("Cells(int,int)", 3, i);
        QString value = cell->dynamicCall("Value2()").toString();
        // 移除列名中的括号
        value.remove(removeParenthesesRegex);
        keyType[i - column_start] = value;
        qDebug() << i - column_start << ":" << keyType[i - column_start];
    }
    // 构建创建表的SQL语句
    QString creatsql = QString("CREATE TABLE %1(").arg(work_sheet_name);//按表头在MySQL中创建新表
    bool isFirstColumn = true;
    for (const QString &columnName : keyType) {
        if (!isFirstColumn) {
            creatsql += ", ";
        }
        isFirstColumn = false;
        // 这里需要映射Excel列的数据类型到MySQL的数据类型
        // 假设所有列都是VARCHAR类型，并指定长度
        creatsql += QString("%1 VARCHAR(255)").arg(columnName);
    }
    creatsql += ");";
    qDebug() << creatsql; // 打印SQL语句以供检查
    QSqlQuery creatquery;
    if(creatquery.exec(creatsql))
        qDebug() << "成功创建表格："<<work_sheet_name;
    else
        qDebug() << "创建表格" << work_sheet_name << "失败。错误信息：" << creatquery.lastError().text();
}

void Widget::InsertData(QAxObject *work_sheet)
{
    QElapsedTimer timer;
    timer.start(); // 开始计时
    QString work_sheet_name = work_sheet->property("Name").toString();  //获取工作表名称
    QAxObject *used_range = work_sheet->querySubObject("UsedRange");//选取当前页面所有已使用单元格
    QAxObject *rows = used_range->querySubObject("Rows");
    QAxObject *columns = used_range->querySubObject("Columns");
    int row_start = used_range->property("Row").toInt();  //获取起始行
    int column_start = used_range->property("Column").toInt();  //获取起始列
    int row_count = rows->property("Count").toInt();  //获取行数
    int column_count = columns->property("Count").toInt();  //获取列数
    qDebug() << "column_count:"<<column_count;

    QSqlDatabase db = QSqlDatabase::database(); // 假设您已经有一个数据库连接
    if (!db.transaction()) { // 开始事务
        // 处理事务开始失败的情况
        qDebug() << "无法开始事务";
        return;
    }
    /*
    QSqlQuery insertquery;
    qDebug() <<"行号：" << row_count;
    qDebug() << "起始行号：" << row_start;
    qDebug() << "列号：" << column_count;
    qDebug() << "起始列号：" << column_start;
    for(int i = row_start + 2; i < row_count;i++)//从行开始
    {
        QString strSql = QString("insert into %1 values(").arg(work_sheet_name);
        for(int j = column_start; j < column_count+column_start;j++)
        {
            QAxObject *cell = work_sheet->querySubObject("Cells(int,int)", i+1, j);//去除第一行表头
            QString Value = cell->dynamicCall("Value2()").toString();
            // 对特殊字符进行转义，防止SQL注入
            Value.replace("'", "''");
            strSql += "'" + Value + "'";
            if (j < column_count) {
                strSql += ",";
            } else {
                strSql += ")";
            }
        }
        qDebug()<<strSql;

        if (!insertquery.exec(strSql)) {
            // 处理 SQL 执行错误
            qDebug() << "SQL 插入错误:" << insertquery.lastError().text();
            db.rollback(); // 回滚事务
            return;
        }
    }

    // 如果没有错误，提交事务
    if (!db.commit()) {
        // 处理提交事务失败的情况
        qDebug() << "提交事务失败";
        return;
    } else {
        qDebug() << "数据插入成功并已提交";
   }
*/
    QSqlQuery insertquery;
    QString strSqlBase = QString("insert into %1 values(").arg(work_sheet_name);
    QStringList valuePlaceholders;
    for (int j = column_start; j < column_count + column_start; j++) {
        valuePlaceholders.append("?");
    }
    QString strSql = strSqlBase + valuePlaceholders.join(",") + ")";
    insertquery.prepare(strSql);

    for (int j = column_start; j < column_count + column_start; j++) {
        QVariantList rowData;
        for (int i = row_start + 2; i < row_count; i++) {
            QAxObject *cell = work_sheet->querySubObject("Cells(int,int)", i + 1, j);
            QString value = cell->dynamicCall("Value2()").toString();
            rowData.append(value);
        }
        insertquery.addBindValue(rowData);
    }

    if (!insertquery.execBatch()) {
        // 处理批量插入错误
        qDebug() << "批量插入错误:" << insertquery.lastError().text();
        db.rollback();
        return;
    }

    if (!db.commit()) {
        // 处理提交错误
        qDebug() << "提交事务失败";
        return;
    } else {
        qDebug() << "数据插入成功并已提交";
    }

    qint64 elapsedTime = timer.elapsed(); // 获取经过的毫秒数
    qDebug() << "插入函数执行时间：" << elapsedTime << "毫秒";

    //验证是否缺少行,不缺少则数据导入成功
    QString resuresql=QString("select count(1) from %1").arg(work_sheet_name);//获取当前行数
    // 初始化一个布尔变量来标记操作是否成功
    bool importSuccessful = false;
    try{
        // 执行SQL查询
        if (insertquery.exec(resuresql)) {
            // 检查是否至少有一行结果返回
            if (insertquery.next()) {
                // 检查行数是否大于0
                if (insertquery.value(0).toInt() > 0) {
                    // 数据导入成功
                    importSuccessful = true;
                } else {
                    // 数据缺失
                    QMessageBox::warning(this, tr("提示："), tr("数据缺失，请重新导入"));
                }
            } else {
                // 没有查询结果返回
                QMessageBox::warning(this, tr("错误："), tr("查询结果为空，请检查SQL语句或数据库连接"));
            }
        } else {
            QSqlError error = insertquery.lastError();
            QMessageBox::warning(this, tr("错误："), tr("SQL执行错误: %1").arg(error.text()));
        }
    }
    catch (const QSqlError &e) {
        QMessageBox::warning(this, tr("异常："), tr("SQL执行时发生异常: %1").arg(e.text()));
    }


    // 如果数据导入成功，则显示消息
    if (importSuccessful) {
        QMessageBox::information(this, tr("提示："), tr("数据导入成功"));
        qDebug() << "1";
    }


}
//截图按键
void Widget::on_screenshot_clicked()
{
    if(widget!=nullptr){
        widget->deleteLater();
        widget=nullptr;
    }
    widget=new ScreenShotWidget();
    widget->showFullScreen();

}

//选择文件
void Widget::on_selectButton_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this, tr("Open Excel file"), "", tr("Excel Files (*.xlsx *.xls)"));//打开选择文件窗口
    if (!filePath.isEmpty())
    {
        qDebug() << "当前打开的文件路径为"<<filePath;//显示文件路径
    }
    QAxObject *excel = new QAxObject("Excel.Application");
    excel->setProperty("Visible", false);// 不显示 Excel 窗体
    QAxObject *work_books = excel->querySubObject("WorkBooks"); //获取工作簿集合
    work_books->dynamicCall("Open (const QString&)", filePath);//打开已存在的工作簿
    QAxObject *work_book = excel->querySubObject("ActiveWorkBook");//获取当前工作簿

    QAxObject *work_sheets = work_book->querySubObject("Sheets");  //Sheets也可换用WorkSheets
    int sheet_count = work_sheets->property("Count").toInt();  //获取工作表数目
    qDebug() << "当前文件有"<<sheet_count<< "张sheet";

    for(int i=1; i<=sheet_count; i++)//循环操作每张sheet
    {
        QAxObject *work_sheet = work_book->querySubObject("Sheets(int)", i);
        QString work_sheet_name = work_sheet->property("Name").toString();  //获取工作表名称
        qDebug() << "工作表名: " << work_sheet_name;


        //查看数据库中是否有相应表格，没有就创建
        if(isTableExists(work_sheet_name))
        {
            int ok = QMessageBox::warning(this,tr("提示："),tr("当前数据库中已经存在该表，"
                                                                 "确认替换吗？ "),QMessageBox::Yes,QMessageBox::No);
            qDebug() << "2";
            if(ok == QMessageBox::No);
            else  //替换
            {
                qDebug()  << "3";
                QSqlQuery query;
                query.exec(QString("drop table if exists %1").arg(work_sheet_name));
                creatNewTable(work_sheet);
                InsertData(work_sheet);
            }
        }
        else
        {
            qDebug() << "4";
            creatNewTable(work_sheet);
            InsertData(work_sheet);
            qDebug() << "5";
        }
    }
    work_book->dynamicCall("Close()");//关闭工作簿
    excel->dynamicCall("Quit()");//关闭 excel
    qDebug() << "6";
    delete excel;
    excel = NULL;
    qDebug() << "7";

}

void Widget::on_showButton_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this, tr("Open Excel file"), "", tr("Excel Files (*.xlsx *.xls)"));
    if (!filePath.isEmpty())
    {
        ui->checklineEdit->setText(filePath);//显示文件路径
        if(!m_xlsx)
            m_xlsx = new QXlsx::Document(filePath,this);        // 打开EXCEL_NAME文件，将所有数据读取到内存中，然后关闭excel文件
        if(m_xlsx->load())  // 判断文件是否打开成功（也可以使用isLoadPackage）,如果文件不存在则为false
            qDebug() << "excel打开并加载成功!";
        else
            qWarning() << "excel打开失败!";
    }
    if(!m_xlsx)  // 判断文件是否打开成功（也可以使用isLoadPackage）,如果文件不存在则为false
    {
        QMessageBox::information(this,"提示","请先点击'打开文件'按钮");
        return;
    }
    int rowLen = m_xlsx->dimension().rowCount();           // 获取最大行数
    int columnLen = m_xlsx->dimension().columnCount();     // 获取最大列数
    qDebug() << "row:"<<rowLen<<"  column:"<<columnLen;
    for(int i = 1; i <= rowLen; i++)                       // 遍历每一行
    {
       // QString data = QString("第%1行：").arg(i);
        for(int j = 1; j <= columnLen; j++)                // 遍历每一个单元格(列)
        {
            QVariant value = m_xlsx->read(i, j); // 通常Excel的行和列是从1开始的，所以这里加1
            QTableWidgetItem *item = new QTableWidgetItem(value.toString());
            ui->tableWidget->setItem(i - 1, j - 1, item);
        }
    }
}


void Widget::on_deriveButton_clicked()
{
    QAxObject *excel = new QAxObject("Excel.Application");//创建了一个QAxObject对象，用于访问Excel应用程序的COM接口。
    if (excel->isNull())//判断是否存在excel
    {
        if (excel != NULL)//网络中很多使用 excel==NULL 判断，是错误的
        {
            excel->dynamicCall("Quit()");//关闭
            delete excel;
        }
        QMessageBox::critical(0, "错误信息", "没有找到 EXCEL 应用程序");
        return;
    }
    QAxObject *workbooks = NULL;
    QAxObject *workbook = NULL;
    QAxObject *worksheets = NULL;
    QAxObject *worksheet = NULL;
    excel->dynamicCall("SetVisible (bool)", true);//不显示窗体
    excel->setProperty("DisplayAlerts", false); //不显示任何警告信息。如果为 true 那么在关闭是会出现类似“文件已修改，是否保存” 的提示
    workbooks = excel->querySubObject("WorkBooks");//获取工作簿集合
    QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"),"",tr("Excel Files (*.xlsx *.xls)"));
    if (QFile::exists(filePath))
    {
        workbook = workbooks->querySubObject("Open(const QString &)", filePath);
    }
    else
    {
        workbooks->dynamicCall("Add");//新建一个工作簿
        workbook = excel->querySubObject("ActiveWorkBook");//获取当前工作簿
    }
    worksheets = workbook->querySubObject("Sheets");//获取工作表集合
    worksheet = worksheets->querySubObject("Item(int)",1);//获取工作表集合的工作表 1，即sheet1
    QAxObject * usedrange = worksheet->querySubObject("UsedRange");//获取该 sheet 的使用范围对象
    QAxObject * rows = usedrange->querySubObject("Rows");
    QAxObject * columns = usedrange->querySubObject("Columns");
    int intRowStart = usedrange->property("Row").toInt();
    int intColStart = usedrange->property("Column").toInt();
    int intCols = columns->property("Count").toInt();
    int intRows = rows->property("Count").toInt();
    QAxObject *cell = NULL;
    int rowCount = ui->tableWidget->model()->rowCount();
    int colCount = ui->tableWidget->model()->columnCount();
    // 清空数据
    for(int i=intRowStart;i <intRowStart + intRows;i++)
    {
        for(int j=intColStart ;j<intColStart+intCols;j++)
        {
            cell = worksheet->querySubObject("Cells(int,int)", i,j ); //获取单元格
            cell->setProperty("Value", "");
        }
    }
    // 插入数据
    for (int i = intRowStart; i < intRowStart+rowCount; i++)
    {
        for(int j = intColStart; j < intColStart+colCount; j++)
        {
            QModelIndex indextemp = ui->tableWidget->model()->index(i-intRowStart, j-intColStart);
            QVariant str = ui->tableWidget->model()->data(indextemp);
            cell = worksheet->querySubObject("Cells(int,int)", i, j);//获取单元格
            cell->setProperty("Value", str);
        }
    }
    QMessageBox::information(this,"提示","数据导出完毕");
    workbook->dynamicCall("SaveAs(const QString&)",QDir::toNativeSeparators(filePath));//保存至 filepath，注意一定要用 QDir::toNativeSeparators 将路径中的"/"转换为"\"，不然一定保存不了。
    qDebug() <<"保存路径为："<< QDir::toNativeSeparators(filePath);
    workbook->dynamicCall("Close()");//关闭工作簿
    excel->dynamicCall("Quit()");//关闭 excel
    delete excel;
    excel = NULL;
}

